#include <conio.h>
#include <tgmath.h>
#include <cstddef>
#include <iostream>
#include <cstdlib>
#include <string>
#include <stdio.h>

#include "include\magic.h"
#include "include\entity.h"

magic::magic()
{
    entity = NULL;
}

magic::magic(Entity *thisEntity)
{
    // Just to let us get a pointer to the entity
}




SpellType magic::GetPlayerSpell() // Some of this should be generalized later, obviously. I am aware that this is kind of copypasta.
{
    SpellType thisSpell = NOSPELL;
    while (thisSpell == NOSPELL)
    {
        cout << "Select Spell: (Q)uick heal [10 magic], (S)low heal [20 magic], (F)ireball [50 magic] or (C)ancel" << endl;
        char inputChar = tolower(getch());
        switch (inputChar)
        {
        case 'q':
            thisSpell = HEALQUICK;
            #ifndef DEBUG_MODE
                system("cls");
            #endif
        break;
        case 's':
            thisSpell = HEALSLOW;
            #ifndef DEBUG_MODE
                system("cls");
            #endif
        break;
        case 'f':
            thisSpell = FIREBALL;
            #ifndef DEBUG_MODE
                system("cls");
            #endif
        break;
        case 'c':
            thisSpell = CANCEL;
        break;
        default:
            cout << "Invalid key press" << endl;
            thisSpell = NOSPELL;
        break;
        }
    }
    return thisSpell;
}

SpellType magic::GetEnemySpell(Entity *pEnemy) // kludgey temporary AI
{
    int randomRoll = rand() % 100;
    if (randomRoll < 40)
    {
        return FIREBALL;
    }
    else if (randomRoll < 60)
    {
        return HEALSLOW;
    }
    else
    {
        return HEALQUICK;
    }
}

int magic::HealQuick(Entity *pHealer, Entity *pTarget)
{
    int healing = rand()% 20 + 5;
    pTarget->SetHealth(pTarget->GetHealth() + healing);
    spellName = "quick heal";
    spellEffectString = string{"heals "} + pTarget->GetName() + string {" for +"} + intToString(healing);
    //cout << pHealer->GetName() << " heals " << pTarget->GetName() << " for +" << healing << endl;
    return healing;

}

int magic::Fireball(Entity *pCaster, Entity *pTarget)
{


    float damage = round((rand()% 40)) + 20;
    pTarget->SetHealth(pTarget->GetHealth() - damage);
    spellName = "fireball";
    spellEffectString = string{"hits "} + pTarget->GetName() + string {" with a fireball for "} + intToString(damage);
//    cout << pCaster->GetName() << " hits " << pTarget->GetName() << " with a fireball for -" << damage << endl;
    int duration = rand()% 5+1;
    pTarget->SetStatus(BURNING, duration, 1);
    return damage;

}

void magic::HealSlow(Entity *pHealer, Entity *pTarget)
{
    int magnitude = rand()% 10+3;
    int duration = rand()% 10+3;
    spellName = "slow healing";
    spellEffectString = string{"heals "} + pTarget->GetName() + string{" for +"}
        + intToString(magnitude) + string{" for "} + intToString(duration) + string{" turns"};
//    cout << pHealer->GetName() << " casts slow healing on " << pTarget->GetName() << " for +" << magnitude << " for " << duration << " turns" << endl;
    pTarget->SetStatus(HEALING, duration, magnitude);
    //return healing;

}

bool magic::SpellCast(Entity *pCaster, Entity *pTarget)
{
    while (true)
    {
        SpellType thisSpell;
        if (pCaster->IsPlayer())
        {
            thisSpell = GetPlayerSpell();
        }
        else
        {
            thisSpell = GetEnemySpell(pCaster);
        }

        if (thisSpell == CANCEL)
        {
            return false;
        }
        bool success = ExecuteSpellCast(thisSpell, pCaster, pTarget);
        if (success)
        {
            return true;
        }

    }
}

bool magic::ExecuteSpellCast(SpellType ThisSpell, Entity *pCaster, Entity *pTarget)
// Spell system will be made more robust and generic in future version. Spells and costs are hard coded for now.
{
    switch (ThisSpell)
    {
    case HEALQUICK:
        if (pCaster->GetMagic() >= 10)
        {
            HealQuick(pCaster, pCaster);
            pCaster->SetMagic(pCaster->GetMagic() - 10);
            thisExecutedSpell = HEALQUICK;
            return true;
        }
    break;
    case HEALSLOW:
        if (pCaster->GetMagic() >= 20)
        {
            HealSlow(pCaster, pCaster);
            pCaster->SetMagic(pCaster->GetMagic() - 20);
            thisExecutedSpell = HEALSLOW;
            return true;
        }
    break;
    case FIREBALL:
        if (pCaster->GetMagic() >= 50)
        {
            Fireball(pCaster, pTarget);
            pCaster->SetMagic(pCaster->GetMagic() - 50);
            thisExecutedSpell = FIREBALL;
            return true;
        }
    break;
    case CANCEL:
        return false;
    break;
    default:
        exit(1);
    break;
    }
    cout << "Not enough magic!" << endl;
    return false;
}

string magic::GetSpellName()
{
        return spellName;
}

string magic::GetSpellEffectString()
{
    return spellEffectString;
}

string magic::intToString(int number)
{
    char numberChar[5];
    sprintf(numberChar, "%d", number);
    return string{numberChar};
}

bool canCast(Entity *pCaster, SpellType checkedSpell)
{
        i


}

